from django.core.mail import EmailMessage
from django.db import models
from werkzeug.security import generate_password_hash, check_password_hash

from apps import AbstractBaseModel, AbstractBaseDocument
from common.enums.person_enums import PersonGenderEnums, PersonRegisterStatusEnums
from common.exceptions import PersonNotExist
from common.utils.other_utils import get_random_secret_key
from common.validate import validate_phone
from mongoengine import fields, Document


# RPC请求日志表
class RPCLog(Document):
    func_name = fields.StringField()
    method = fields.StringField()
    request_body = fields.StringField()
    request_headers = fields.StringField()
    response_body = fields.StringField()
    response_headers = fields.StringField()
    startTime = fields.IntField()  # 开始时间
    endTime = fields.IntField()  # 结束时间
    operatorId = fields.IntField()  # 操作人id
    operatorName = fields.StringField()  # 操作人姓名
    operateTime = fields.IntField()  # 操作时间

    meta = {
        'verbose_name': 'RPC请求日志',
        'ordering': ['-operateTime'],
        'indexes': [
            'func_name',
            'method',
            'operatorId'
        ]
    }


# 应用信息表
class Application(AbstractBaseModel):
    appId = models.IntegerField(help_text = '应用id', unique = True)
    appName = models.CharField(max_length = 255, help_text = '应用名称')
    appSecret = models.CharField(max_length = 255, help_text = '应用秘钥', default = get_random_secret_key)
    appIcon = models.CharField(max_length = 255, null = True, blank = True, help_text = '应用图标')
    appDesc = models.CharField(max_length = 255, null = True, blank = True, help_text = '应用描述')

    class Meta:
        verbose_name = 'Application'
        verbose_name_plural = verbose_name
        db_table = 'tApplication'
        ordering = ['-createTime']


# 用户注册信息记录表
class PersonRegisterHistory(AbstractBaseModel):
    username = models.CharField(max_length = 255, help_text = '用户名')
    realName = models.CharField(max_length = 100, null = True, blank = True, help_text = '姓名')
    password = models.CharField(max_length = 255, help_text = '密码')
    avatar = models.CharField(max_length = 255, null = True, blank = True, help_text = '头像')
    phone = models.CharField(max_length = 11, null = True, blank = True,
                             validators = [validate_phone],
                             help_text = '手机号', )
    email = models.EmailField(null = True, blank = True, help_text = '邮箱')
    gender = models.IntegerField(default = PersonGenderEnums.MALE.key, help_text = '性别')
    registerStatus = models.IntegerField(default = PersonRegisterStatusEnums.REGISTERING.key, help_text = '注册状态')
    registerReason = models.CharField(max_length = 255, null = True, blank = True, help_text = '注册失败的原因')

    class Meta:
        verbose_name = 'PersonRegisterHistory'
        verbose_name_plural = verbose_name
        db_table = 'tPersonRegisterHistory'
        ordering = ['-createTime']


class PersonManager(models.Manager):
    use_in_migrations = True

    def _create_person(self, username: str, email: str, phone: str, password: str, **extra_field):
        """穿件用户"""
        person = self.model(
            username = username,
            email = email,
            phone = phone,
            password = generate_password_hash(password),
            **extra_field
        )
        person.save(using = self._db)

        return person

    def _register_person(self, personRegisterHistory: PersonRegisterHistory):
        """注册用户"""
        person = self.model(
            username = personRegisterHistory.username,
            realName = personRegisterHistory.realName,
            password = personRegisterHistory.password,
            avatar = personRegisterHistory.avatar,
            email = personRegisterHistory.email,
            gender = personRegisterHistory.gender
        )

        person.save(using = self._db)
        return person

    def _change_password(self, username: str, password: str):
        """修改密码"""
        queryset = self.model.objects.filter(username = username, deleted = False)
        if queryset.count() == 0:
            raise PersonNotExist(f'{username}不存在')
        person = queryset.first()
        person.password = generate_password_hash(password)
        person.save(using = self._db)
        return person

    def create_person(self, username: str, email: str, phone: str, password: str, **extra_field):
        return self._create_person(username, email, phone, password, **extra_field)

    def create_super_person(self, username: str, email: str, phone: str, password: str, **extra_field):
        extra_field.setdefault('isSuper', True)
        extra_field.setdefault('isActive', True)
        return self._create_person(username, email, phone, password, **extra_field)

    def register_person(self, personRegisterHistory: PersonRegisterHistory):
        return self._register_person(personRegisterHistory)

    def change_password(self, username: str, password: str):
        pass


# 用户信息表
class Person(AbstractBaseModel):
    username = models.CharField(max_length = 255, help_text = '用户名')
    realName = models.CharField(max_length = 100, null = True, blank = True, help_text = '姓名')
    password = models.CharField(max_length = 255, help_text = '密码')
    avatar = models.CharField(max_length = 255, null = True, blank = True, help_text = '头像')
    phone = models.CharField(max_length = 11, null = True, blank = True,
                             validators = [validate_phone],
                             help_text = '手机号', )
    email = models.EmailField(null = True, blank = True, help_text = '邮箱')
    gender = models.IntegerField(help_text = '性别', default = PersonGenderEnums.MALE.key)
    isSuper = models.BooleanField(default = False, help_text = '是否是超级管理员')
    isActive = models.BooleanField(default = False, help_text = '用户状态是否可用')
    lastLoginTime = models.BigIntegerField(null = True, blank = True, help_text = '最后登陆时间')

    objects = PersonManager()

    class Meta:
        verbose_name = 'Person'
        verbose_name_plural = verbose_name
        db_table = 'tPerson'
        unique_together = ('username', 'deleted', 'id')
        ordering = ['-createTime']

    def email_user(self, subject, message, from_email=None, **kwargs):
        """Send an email to this user."""
        EmailMessage(subject, message, from_email, [self.email], **kwargs).send()

    def set_password(self, raw_password):
        self.password = generate_password_hash(raw_password)

    def check_password(self, raw_password):
        return check_password_hash(self.password, raw_password)


class PersonLoginLog(AbstractBaseDocument):

    # 浏览器
    browser = fields.StringField(null = True)
    # 操作系统
    os = fields.StringField(null = True)
    # 最后登陆时间
    lastLoginTime = fields.IntField(null = True)
    # 登陆用户名
    username = fields.StringField(null = True)
    # 登陆token
    token = fields.StringField(null = True)
    # 登陆ip
    ipaddr = fields.StringField(null = True)
    # msg
    msg = fields.StringField(null = True)
    # status
    status = fields.IntField(null = True)
    # 设备
    device = fields.StringField(null = True)
    # 登陆地点
    loginLocation = fields.StringField(null = True)

    meta = {
        'verbose_name': '登陆日志',
        'ordering': ['-createTime'],
    }